const webpack = require('webpack');
const { merge } = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 生成html
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 分离CSS
const WebpackBar = require('webpackbar');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const ESLintPlugin = require('eslint-webpack-plugin');

const paths = require('./paths');

const isDev = ['dev'].includes(process.env.FIG_ENV);
const extensionWebpackConfig = require(`./webpack.${isDev ? 'dev' : 'prod'}.js`);

let shouldUseSourceMap = process.env.GENERATE_SOURCEMAP === 'false';
if (isDev) shouldUseSourceMap = true;

const cssRegex = /\.css$/;
const cssModuleRegex = /\.module.css$/;
const lessRegex = /\.(less|scss)$/;
const lessModuleRegex = /\.module.(less|scss)$/;

const getStyleLoaders = (cssOptions, preProcessor) => {
  const loaders = [
    isDev && 'style-loader',
    !isDev && {
      loader: MiniCssExtractPlugin.loader,
      options: {
        // esModule: false,
        publicPath: '../',
      },
    },
    {
      loader: 'css-loader',
      options: {
        importLoaders: 1,
        modules: {
          localIdentName: '[local]__[hash:base64:5]',
        },
        sourceMap: shouldUseSourceMap,
        ...cssOptions,
      },
    },
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          ident: 'postcss',
        },
      },
    },
    {
      loader: 'style-resources-loader',
      options: {
        patterns: [paths.appCssVariable],
      },
    },
  ].filter(Boolean);

  if (preProcessor) {
    if (Array.isArray(preProcessor)) {
      loaders = [...loaders, ...preProcessor];
    } else {
      loaders.push(preProcessor);
    }
  }

  return loaders;
};

const baseWebpackConfig = {
  target: 'web',
  entry: {
    app: [
      // 'core-js',
      paths.appIndexJs,
    ],
  },
  output: {
    path: paths.appBuild,
    publicPath: paths.publicUrlOrPath,
    library: `${paths.appPackageJson.name}-[name]`,
    libraryTarget: 'umd',
    globalObject: 'this',
  },
  module: {
    rules: [
      {
        test: /\.(ts|tsx|js|jsx)$/,
        include: [paths.appSrc],
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true,
              sourceMaps: shouldUseSourceMap,
              inputSourceMap: shouldUseSourceMap,
            },
          },
        ],
      },
      {
        test: cssRegex,
        exclude: cssModuleRegex,
        use: getStyleLoaders({
          modules: false,
        }),
        sideEffects: true,
      },
      {
        test: cssModuleRegex,
        use: getStyleLoaders({}),
      },
      {
        test: lessRegex,
        // include: [paths.appSrc, /node_modules\/antd/],
        exclude: lessModuleRegex,
        use: getStyleLoaders(
          {
            modules: false,
          },
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                javascriptEnabled: true,
              },
              sourceMap: shouldUseSourceMap,
            },
          },
          {
            loader: 'sass-loader',
          },
        ),
        sideEffects: true,
      },
      {
        test: lessModuleRegex,
        include: [paths.appSrc],
        use: getStyleLoaders({}, 'less-loader', 'sass-loader'),
      },
      /* 解析图片-放到指定img路径 */
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/,
        include: [paths.appSrc],
        type: 'asset', // 自动识别
        generator: {
          filename: 'static/img/[name][ext]',
        },
        parser: {
          dataUrlCondition: {
            maxSize: 1024 * 4, // 超过 4kb 进行内联模块，图片就转换base64
          },
        },
      },
      /* 字体文件加载器-放到指定路径 */
      {
        test: /\.(eot|otf|ttf|woff|woff2)$/,
        type: 'asset/resource',
        include: [paths.appSrc],
        generator: {
          filename: 'static/font/[name][ext]',
        },
      },
    ],
  },
  resolve: {
    alias: {
      '@': paths.appSrc,
      'react/jsx-dev-runtime': 'react/jsx-dev-runtime.js',
      'react/jsx-runtime': 'react/jsx-runtime.js',
    },
    extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
    modules: ['node_modules'], // 指定查找插件目录
    fallback: {
      module: 'empty',
      dgram: 'empty',
      dns: 'mock',
      fs: 'empty',
      http2: 'empty',
      net: 'empty',
      tls: 'empty',
      child_process: 'empty',
      buffer: require.resolve('buffer'),
      process: require.resolve('process/browser'),
      zlib: require.resolve('browserify-zlib'),
      stream: require.resolve('stream-browserify'),
      util: require.resolve('util'),
      asset: require.resolve('assert'),
      fs: require.resolve('browserify-fs'),
    },
  },
  plugins: [
    process.env.ANA_TYPE === 'true' && new BundleAnalyzerPlugin({ analyzerPort: 'auto' }),

    new ESLintPlugin({
      fix: true,
      lintDirtyModulesOnly: true,
    }),

    new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn/),
    // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new HtmlWebpackPlugin({
      template: paths.appHtml,
      favicon: paths.appIco,
      inject: true,
      minify: {
        removeComments: !isDev, // 移除HTML中的注释
        collapseWhitespace: !isDev, // 删除空白符与换行符
        removeAttributeQuotes: true, // 去除属性引用
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      },
      config: {
        FIG_ENV: process.env.FIG_ENV,
      },
    }),

    new MiniCssExtractPlugin({
      filename: isDev ? 'static/css/[name].css' : 'static/css/[name].[contenthash:6].css',
      chunkFilename: isDev
        ? 'static/css/[name].chunk.css'
        : 'static/css/[name].[contenthash:6].chunk.css',
      ignoreOrder: true,
    }),

    new webpack.ProvidePlugin({
      Buffer: ['buffer', 'Buffer'],
      process: require.resolve('process/browser'),
    }),

    new webpack.DefinePlugin({
      'process.env': JSON.stringify(process.env),
    }),

    new WebpackBar({
      name: paths.appPackageJson.name,
      color: '#00AFF2',
      profile: true,
      minimal: false,
      compiledIn: false,
    }),
  ].filter(Boolean),
  node: {
    // global: false,
    // __filename: false,
    // __dirname: false,
  },
  // externals: {
  //   react: 'React',
  //   'react-dom': 'ReactDOM',
  // },
};

module.exports = merge(baseWebpackConfig, extensionWebpackConfig(paths));
